/**判断点是否在圆内
 * @param {{x:number,y:number}} point -- 点的坐标
 * @param {{x:number,y:number,r:number}} img -- 圆的信息
 * @returns 
 */
function inCircle(point,circle){
    let dis = Math.sqrt(Math.pow(point.x - circle.x,2) + Math.pow(point.y - circle.y,2));
    return dis <= circle.r/2;
}

// 判断图形是否在一封闭路径内
function inClosedPath(point,paths){
    var inside = false;
    for(let i = 0,l = paths.length; i < l ; i++){
        let linePoint1 = paths[i];
        let linePoint2 = i == l - 1 ? paths[0] : paths[i+1];
        let slope = (linePoint2.y - linePoint1.y) / (linePoint2.x - linePoint1.x);
        // 判断点是否在线段的x轴之间
        let betweenX = (linePoint1.x < point.x && linePoint2.x > point.x) || (linePoint1.x > point.x && linePoint2.x < point.x);
        // 以point作一条平行于Y轴的射线，判断射线与经过linePoint1和linePoint2两点的直线的交点,是否位于point的y轴的上方
        let intersect = point.y < (slope * (point.x - linePoint1.x) + linePoint1.y);
        
        if(betweenX && intersect){
            inside = !inside;
        }
    }
    return inside;
}

// 是否在线上
function inLine(point,line){
    // 计算线条的斜率
    let rectData = []
    if(line.st_x == line.sp_x || line.st_y == line.sp_y){
        rectData.push({
            x: line.st_x + line.width / 2,
            y: line.st_y + line.width / 2
        });
        rectData.push({
            x: line.sp_x + line.width / 2,
            y: line.sp_y + line.width / 2
        });
        rectData.push({
            x: line.sp_x - line.width / 2,
            y: line.sp_y - line.width / 2
        });
        rectData.push({
            x: line.st_x - line.width / 2,
            y: line.st_y - line.width / 2
        });
    }else{
        let k = (line.st_y - line.sp_y) / (line.st_x - line.sp_x);
        let slope = -1/k;
        // x = x1±Math.sqrt(d/(k^2+1));
        let base = Math.sqrt(Math.pow(line.width / 2,2) / (slope * slope + 1));
        let point1 = {
            x: line.st_x + base,
            y: base * slope + line.st_y,
        }
        let point2 = {
            x: line.st_x - base,
            y: -base * slope + line.st_y,
        }
        let point3 = {
            x: base + line.sp_x,
            y: base * slope + line.sp_y,
        }
        let point4 = {
            x: line.sp_x - base,
            y: -base * slope + line.sp_y,
        }
        rectData.push(point1);
        rectData.push(point3);
        rectData.push(point4);
        rectData.push(point2);
    }
    return this.inClosedPath(point,rectData);
}

// 是否在弧上
function inArc(point,arc){
    let x = point.x,y = -point.y;
    let status=false,
        r=arc.r,
        st_x=arc.st_x,
        st_y=-arc.st_y,
        sp_x=arc.sp_x,
        sp_y=-arc.sp_y,
        line_w=arc.width/2,
        o_x=arc.o_x,
        o_y=-arc.o_y,
        dir=arc.arc_r,
        rot = arc.rotate;
    let gap=Math.sqrt((Math.pow(x-o_x,2)+Math.pow(y-o_y,2)));
    if(r-line_w<gap&&gap<r+line_w){//满足圆的方程
        let median=sountAngle(x-o_x ,  y-o_y),
            st = sountAngle(st_x-o_x, st_y-o_y),
            sp = sountAngle(sp_x-o_x, sp_y-o_y);
        //计算夹角
        let angle_ref=[],
            angle_acc=[],
            angle_st=180*st.angle/Math.PI,
            angle_me=180*median.angle/Math.PI,
            angle_sp=180*sp.angle/Math.PI;
        angle_ref=[angle_st,angle_sp];
        let maxAngle=Math.max.apply(null,angle_ref),
            minAngle=Math.min.apply(null,angle_ref);
        if(st_x==sp_x&&st_y==sp_y){
            status=true;
        }else{
            //判断夹角是否过0点
            let angle_lock=false,
                qua_st=st.qua,
                qua_sp=sp.qua;
            if(dir === "t"){//顺时针
                if(qua_st==1&&qua_sp==2||qua_st==1&&qua_sp==3
                    ||qua_st==1&&qua_sp==4||qua_st==2&&qua_sp==3
                    ||qua_st==2&&qua_sp==4||qua_st==3&&qua_sp==4
                    ){
                    angle_lock=true;
                }else if(qua_st==1&&qua_sp==1
                    ||qua_st==4&&qua_sp==4){
                    if(st_y<sp_y){
                        angle_lock=true;
                    }
                }else if(qua_st==2&&qua_sp==2
                    ||qua_st==3&&qua_sp==3){
                    if(st_y>sp_y){
                        angle_lock=true;
                    }
                }
            }else{//逆时针
                if(qua_st==2&&qua_sp==1||qua_st==3&&qua_sp==1
                ||qua_st==3&&qua_sp==2||qua_st==4&&qua_sp==1
                ||qua_st==4&&qua_sp==2||qua_st==4&&qua_sp==3){
                    angle_lock=true;
                }else if(qua_st==1&&qua_sp==1
                    ||qua_st==4&&qua_sp==4){
                    if(st_y>sp_y){
                        angle_lock=true;
                    }
                }else if(qua_st==2&&qua_sp==2
                    ||qua_st==3&&qua_sp==3){
                    if(st_y<sp_y){
                        angle_lock=true;
                    }
                }
            }
            if(angle_lock){
                if(minAngle<angle_me&&angle_me<maxAngle){
                    status=true;
                }
            }else{
                
                if(minAngle>=angle_me||angle_me>maxAngle){
                    status=true;
                }
            }
        }
    }
    return status;

    function sountAngle(x,y){
        var angle=0,
            qua=0;
        if(x>0&&y>=0){
            angle=Math.atan(y/x);
            qua=1;
        }else if(x<=0&&y>0){
            x=Math.abs(x);
            angle=Math.atan(x/y)+0.5*Math.PI;
            qua=2;
        }else if(x<0&&y<=0){
            x=Math.abs(x);
            y=Math.abs(y);
            angle=Math.atan(y/x)+Math.PI;
            qua=3;
        }else if(x>=0&&y<0){
            y=Math.abs(y);
            angle=Math.atan(x/y)+1.5*Math.PI;
            qua=4;
        }
        return {
            angle:angle,
            qua:qua,
        };
    
    }
}

// 是否在矩形内
function inRect(point,rect){
    let paths = [];
    paths.push({
        x: rect.x + rect.w / 2,
        y: rect.y + rect.h / 2
    });
    paths.push({
        x: rect.x + rect.w / 2,
        y: rect.y - rect.h / 2
    });
    paths.push({
        x: rect.x - rect.w / 2,
        y: rect.y - rect.h / 2
    });
    paths.push({
        x: rect.x - rect.w / 2,
        y: rect.y + rect.h / 2
    });
    if(rotate){
        paths = computedUtil.rotatePoints(paths,{x:rect.x, y:rect.y},rotate);
    }
    return this.inClosedPath(point,paths);
}

/**
 * 逆时针旋转
 * @param {{x:number,y:number}} point 
 * @param {{x:number,y:number}} center 
 * @param {number} rotate 
 * @returns 
 */
function rotatePoint(point,center,rotate){
    if(!rotate){
        return point;
    }
    let angle = rotate * Math.PI / 180;
    return {
        x: (point.x - center.x) * Math.cos(angle) - (point.y - center.y) * Math.sin(angle) + center.x,
        y: (point.x - center.x) * Math.sin(angle) + (point.y - center.y) * Math.cos(angle) + center.y
    }
}

/**
 * 逆时针旋转
 * @param {Array} points 
 * @param {*} center 
 * @param {*} rotate 
 * @returns 
 */
function rotatePoints(points,center,rotate){
    return points.map(point=>this.rotatePoint(point,center,rotate));
}
// 旋转range
/**
 * 
 * @param {{x:[],y:[]}} range 
 * @param {number} rotate 
 * @param {?{x:number,y:number}} center 
 * @returns 
 */
function rotateRange(range,rotate,center){
    if(!center){
        center = {
            x: (range.x[0] + range.x[1]) / 2,
            y: (range.y[0] + range.y[1]) / 2,
        }
    }
    let points = [
        {x:range.x[1],y:range.y[0]},
        {x:range.x[1],y:range.y[1]},
        {x:range.x[0],y:range.y[0]},
        {x:range.x[0],y:range.y[1]}
    ];

    points = computedUtil.rotatePoints(points,center,rotate);

    var maxX = points[0].x,maxY = points[0].y,minX = points[0].x,minY = points[0].y;
    points.forEach(point => {
        if(maxX < point.x){
            maxX = point.x;
        }
        if(maxY < point.y){
            maxY = point.y;
        }
        if(minX > point.x){
            minX = point.x;
        }
        if(minY > point.y){
            minY = point.y;
        }
    });
    return {
        x:[minX, maxX],
        y:[minY, maxY]
    };
}

 // 合并范围
function compareRange(range,toRange){
    if(!toRange){
        return {
            x:[
                range.x[0],
                range.x[1]
            ],
            y:[
                range.y[0],
                range.y[1]
            ]
        };
    }
    if(!range){
        return {
            x:[
                toRange.x[0],
                toRange.x[1]
            ],
            y:[
                toRange.y[0],
                toRange.y[1]
            ]
        };
    }
    var compare = {
        x:[0,0],
        y:[0,0]
    }
    compare.x[0] = toRange.x[0] < range.x[0] ? toRange.x[0] : range.x[0];
    compare.x[1] = toRange.x[1] > range.x[1] ? toRange.x[1] : range.x[1];
    compare.y[0] = toRange.y[0] < range.y[0] ? toRange.y[0] : range.y[0];
    compare.y[1] = toRange.y[1] > range.y[1] ? toRange.y[1] : range.y[1];
    return compare;
}

// 圆矩转路径
/**
 * 
 * @param {{
 * r:number //圆角半径, 
 * width: number,
 * height: number,
 * }} cs 
 * @returns 
 */
function cs2Path(cs){
    let r = cs.r;
    let originR = r;
    let w = cs.w;
    let h = cs.h;
    let x = 0, y=0;
    let arc_r = r < 0 ? "nil" : "t";
    r = Math.abs(r);
    var x1 = x - (w/2 - r),
        y1 = y+ h/2,
        x2 = x + (w/2 - r),
        y2 = y1,

        j1_x= x + w / 2 - r,   
        j1_y = y1 - r,   
                        
        x3 = x2 + r,      
        y3 = y2 - r,

        x4 = x3,

        y4 = y - (h/2 - r),

        j2_x = x4 - r,   
        j2_y = y4,   
                        
        x5 = x4 - r,        
        y5 = y4 - r,

        x6 = x - (w/2 - r),
        y6 = y5,

        j3_x = x6,
        j3_y = y6 + r,
        
        x7 = x6 - r,
        y7 = y6 + r,

        x8 = x7,
        y8 = y + (h/2 -r),

        j4_x = x8 + r,
        j4_y = y8;

    if(originR<0){
        j1_x = x + w / 2,   
        j1_y = y + h / 2,   
        j2_x = x + w / 2,   
        j2_y = y - h / 2,   
        j3_x = x - w / 2,
        j3_y = y - h / 2,
        j4_x = x - w / 2,
        j4_y = y + h / 2;
    }
    
    let path = [];
    path.push(point2Line([x1,y1],[x2,y2]));
    path.push(point2Arc([x2,y2],[x3,y3],[j1_x,j1_y],r,arc_r));
    path.push(point2Line([x3,y3],[x4,y4]));
    path.push(point2Arc([x4,y4],[x5,y5],[j2_x,j2_y],r,arc_r));
    path.push(point2Line([x5,y5],[x6,y6]));
    path.push(point2Arc([x6,y6],[x7,y7],[j3_x,j3_y],r,arc_r));
    path.push(point2Line([x7,y7],[x8,y8]));
    path.push(point2Arc([x8,y8],[x1,y1],[j4_x,j4_y],r,arc_r));
    return path;
}

// point2Line 路径点转线
function point2Line(point1,point2,width){
    let line = {
        st_x:point1[0],
        st_y:point1[1],
        sp_x:point2[0],
        sp_y:point2[1],
        width:width || 0,
        name:"LINE",
        arc_r:"nil",
        o_x: 0,
        o_y: 0,
        r:0
    }
    return line;
}

// point2Arc 路径点转弧
function point2Arc(point1,point2,oPoint,r,dir,width){
    let arc = {
        st_x:point1[0],
        st_y:point1[1],
        sp_x:point2[0],
        sp_y:point2[1],
        width:width || 0,
        name:"ARC",
        arc_r:dir || "nil",
        o_x: oPoint[0],
        o_y: oPoint[1],
        r:r
    };
    return arc;
}

export {
    inCircle,
    inClosedPath,
    inLine,
    inArc,
    inRect,
    rotatePoint,
    rotatePoints,
    compareRange,
    rotateRange,
    cs2Path
}